#include "Spark/Net/EventLoopThreadPool.h"
#include <algorithm>
#include <cassert>
#include <iterator>

EventLoopThreadPool::EventLoopThreadPool(EventLoop *base, std::string name)
    : baseLoop_(base),
      name_(std::move(name)),
      poolStart_{false},
      threadNums_(0),
      loopIndex_(0)
{
}

EventLoopThreadPool::~EventLoopThreadPool()
{
}

void EventLoopThreadPool::start()
{
    assert(!poolStart_);
    assert(baseLoop_->isInLoopThread());
    for (int i = 0; i < threadNums_; ++i)
    {
        vThreads_.emplace_back(new EventLoopThread(name_ + std::to_string(i)));
        vThreads_.back()->run();
        loops_.push_back(vThreads_.back()->getLoop());
    }
    poolStart_ = true;
}

EventLoop *EventLoopThreadPool::getNextLoop()
{
    assert(baseLoop_->isInLoopThread());
    assert(poolStart_);
    EventLoop *loop = baseLoop_;
    if (!vThreads_.empty())
    {
        loop = loops_[loopIndex_];
        ++loopIndex_;
        if (loopIndex_ >= vThreads_.size())
            loopIndex_ = 0;
    }
    return loop;
}

EventLoop *EventLoopThreadPool::getLoop(size_t id)
{
    if (id < vThreads_.size())
        return vThreads_[id]->getLoop();
    return nullptr;
}

std::vector<EventLoop *> EventLoopThreadPool::getAllLoops() const
{
    assert(baseLoop_->isInLoopThread());
    assert(poolStart_);
    if (loops_.empty())
    {
        return std::vector<EventLoop *>(1, baseLoop_);
    }
    return loops_;
}
